// Software License Agreement (BSD License) 
// Copyright (c) 2008, OMNESOFT, L.L.C.
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following 
// conditions are met:
// 
// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 
// in the documentation and/or other materials provided with the distribution.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
// NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
// THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

spinetail = new Object(); // The spinetail object exists in the global scope

spinetail.exceptions = {
	"E1100": "No view specified in url, no default view name", 
	"E1101": "Cannot deserialize controller", 
	"E1102": "Exception dispatching view", 
	"E1103": "Controller missing main() method"};

spinetail.currentException = null;

spinetail.defaultViewName = "index";

spinetail.currentViewName = null;

spinetail.currentView = null;

spinetail.currentController = null;

spinetail.currentParameters = {"paramCount": 0};

spinetail.ajaxCallback = null;

spinetail.model = {};

// The "program"
spinetail.dispatch = function() {
	this.initializeCurrentViewName(); // Throws exception
	if(this.currentException !== null) return this.currentException.exceptionCode;
	
	this.initializeCurrentParameters();
	
	this.initializeCurrentController(); // Throws exception
	if(this.currentException !== null) return this.currentException.exceptionCode;
	
	this.initializeCurrentView(); // Throws exception
	if(this.currentException !== null) return this.currentException.exceptionCode;
	
	return true;
};

// Check that a view is specified in url string or that a defaultViewName is defined; initialize currentViewName
spinetail.initializeCurrentViewName = function() {
	try
	{
		var re = new RegExp("view=(.+?)(&|$)");
		var matchArray = re.exec(window.location.href);
		
		if(matchArray[1] !== undefined) this.currentViewName = matchArray[1];
	} catch (e) {}
	finally {
		if((this.currentViewName === null) || (this.currentViewName === undefined)) {
			this.currentViewName = this.defaultViewName;
			try {
				if(!this.currentViewName) throw this.exception("E1100");
			} catch (e)
			{
				return false;
			}
		}
		return true;
	}
};

// Create an object from url parameters (if there are any)
spinetail.initializeCurrentParameters = function() {
	try
	{
		var re = new RegExp("&(.+?)($)");
		var matchArray = re.exec(window.location.href);
		
		if(matchArray[1] !== undefined) {
			var paramsArray = matchArray[1].split("&");
			this.currentParameters.paramCount = paramsArray.length;
			for(var i = 0; i < paramsArray.length; i++) {
				paramsArray[i].replace("&", null);
				var keyValueArray = paramsArray[i].split("=");
				this.currentParameters[keyValueArray[0]] = unescape(keyValueArray[1]);
			}
		}
	} catch (e) {}
	finally {
		if(this.currentParameters.paramCount === 0)
		{
			return false;
		}
		else return true;
	}
};

// Fetch and deserialize controller to currentController object
spinetail.initializeCurrentController = function() {
	spinetail.controllerCallback = function(id, data) {
		spinetail.currentController = data;		
		if(this.currentController === null)
		{
			throw this.exception("E1101");
		}
		
		if(this.currentController.main === undefined) {
			throw this.exception("E1103");
		}
	}

	try
	{
		axton.data.ajax.quickGET("_controllers/" + this.currentViewName + ".json", new axton.eventManager.EventHandler(spinetail, "controllerCallback"), null, {wait : true, JSONEvilCheck : false});

		
	} catch(e) {
		return false;
	}
	
	return true;
};

// Fetch HTML view content for the current view
spinetail.initializeCurrentView = function() {
	spinetail.viewCallback = function(id, data) {
		spinetail.currentView = data;
		if(this.currentView === null)
		{
			throw this.exception("E1102");
		} 
	    document.getElementById("view").innerHTML = spinetail.currentController.main(spinetail.currentView);
	}

	try
	{
		axton.data.ajax.quickGET("_views/" + this.currentViewName + ".html", new axton.eventManager.EventHandler(spinetail, "viewCallback"), null, {wait : true, JSONEvilCheck : false});
		
		
	} catch(e) {
		return false;
	}
	
	
	return true;
};

// Initialize the current exception object
spinetail.exception = function(exceptionCode) {
	this.currentException = {"exceptionCode": exceptionCode, "exceptionMessage": this.exceptions[exceptionCode]};
	
	document.getElementById("exceptionCode").innerHTML = this.currentException.exceptionCode;
	document.getElementById("exceptionMessage").innerHTML = this.currentException.exceptionMessage;
	
	return this.currentException;
};

// The guts of spinetail's templating "engine" :-)~
spinetail.replaceInView = function(source, searchFor, replaceWith) {
	return source.replace("%%" + searchFor + "%%", replaceWith);
}
